package sii.fb.emotion;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import sii.fb.emotion.bean.Post;
import sii.fb.emotion.bean.User;
import sii.fb.emotion.computProbability.SupportMethod;

public class AssignEmotionPersonality {
	public void AssignEmotionsAndPersonality(Map<Long, List<Post>> user2post, Map<String,List<Integer>> word2cat, Map<Long, User> users){
		SupportMethod cp = new SupportMethod();
		Float[] emotionPosts = new Float[]{0F,0F,0F,0F,0F,0F,0F,0F,0F,0F,0F};
		int post = 0;
		float[] emotion;
		List<Integer> personality;
		for(Long u_id: user2post.keySet()){
			User u = users.get(u_id);
			personality = new LinkedList<Integer>();
			emotion =  new float[10];
			List<Post> me_post = user2post.get(u_id);
			for(Post p: me_post){
				post++;
				String msg = p.getMessage();
				StringTokenizer s = new StringTokenizer(msg," |,|.|!|...|.....|:");
				while(s.hasMoreTokens()){
					String word = s.nextToken();
					if(word2cat.containsKey(word)){
						personality.addAll(word2cat.get(word));
						emotion = defineWordEmotion(word2cat.get(word), word, emotion);
					}
					else{
						for(String key: word2cat.keySet()){
							if(key.endsWith("*")){
								int length = key.length();
								if(word.length()>=length){
									if(word.substring(0,length-1).equals(key.substring(0,length-1))){
										personality.addAll(word2cat.get(key));
										emotion = defineWordEmotion(word2cat.get(key), key, emotion);
									}
								}
							}
						}
					}
				}
				p.setEmotion(emotion);
				cp.updateListPostEmotion(p, emotionPosts); // create complete emotion posts list

			}
			u.setPersonality(definePersonality(personality));
		}
		cp.normalizeListPostEm(emotionPosts, post); //normalize complete emotion posts list
	}
	
	//As in the paper, I say that a status update conveys
	//an emotion if it contains at least one term from the dictionary that is associated
	//with that emotion
	
	//Assign post emotions
	private float[] defineWordEmotion(List<Integer> dictionary, String word, float[] post_emotion){
		//List<Integer> word_emotion = new LinkedList<Integer>();
		if(dictionary.contains(13)||dictionary.contains(14)||dictionary.contains(15))
		 	post_emotion[0] = 1; //post_emotion[0]+1; //Positive
		if(dictionary.contains(16)){
			post_emotion[1] = 1; //post_emotion[1]+1; //Negative
		}
		if(dictionary.contains(17)||dictionary.contains(18)){
			post_emotion[2] = 1; //post_emotion[2]+1; //Anger
		}
		if(dictionary.contains(16)||dictionary.contains(40)||(dictionary.contains(20)&&dictionary.contains(24)
				&&(word.startsWith("atte")||word.startsWith("aspet")))){
			post_emotion[3] =  1; //post_emotion[3]+1; //Anticipation
		}
		if(dictionary.contains(12)&&dictionary.contains(16)&&dictionary.contains(18) &&
				(word.startsWith("disg")||word.startsWith("schif")||word.startsWith("amar"))){
			post_emotion[4] =  1; //post_emotion[4]+1; //Disgust
		}
		if(dictionary.contains(12)&&dictionary.contains(16)&&dictionary.contains(17)){
			if(dictionary.contains(18)|| word.startsWith("paur")){
				post_emotion[5] =  1; //post_emotion[5]+1; //Fear
			}else if(word.startsWith("ang")||word.startsWith("tremend")){
				post_emotion[4] =  1; //post_emotion[4]+1; //Disgust
			}else if(word.startsWith("impaz")){
				post_emotion[3] =  1; //post_emotion[3]+1; //Anticipation
			}
		}
		if(dictionary.contains(15)){
			post_emotion[6] =  1; //post_emotion[6]+1; //Joy
		}
		if(dictionary.contains(19)){
			post_emotion[7] =  1; //post_emotion[7]+1; //Sadness
		}
		if(dictionary.contains(12)&&dictionary.contains(13)&&word.startsWith("sorpr")||word.startsWith("indov")){ //||word.startsWith("possibil")){ //"******COSA??"
			post_emotion[8] =  1; //post_emotion[8]+1;//Surprise
		}
		if(dictionary.contains(12)&&dictionary.contains(13)&&dictionary.contains(15)&&word.startsWith("fid"))
			post_emotion[9] = 1; // post_emotion[9]+1;//Trust
		return post_emotion;
	}
	
	public String[] definePersonality(List<Integer> userPostEmotions){
		int[] personality = new int[]{0,0,0,0,0};
		for(int i=0; i<userPostEmotions.size(); i++){
			int e = userPostEmotions.get(i);
			if(e==15||e==25||e==33||e==36||e==54||e==55||e==57||e==58||e==72||e==80){
				personality[0]++;
			}
			if(e==21||e==24||e==26||e==40||e==47||e==48||e==49||e==50||e==80){
				personality[1]++;
			}
			if(userPostEmotions.contains(new Integer(22))&&(e==3||e==6||e==31||e==34||e==36||e==46||e==51||e==53||e==69||e==70||e==71)){
				personality[2]++;
			}
			if(e==8||e==23||e==30||e==31||e==32||e==34||e==35){
				personality[3]++;
			}
			if(e==16||e==17||e==18||e==19||e==38||e==56||e==59||e==64||e==66){
				personality[4]++;
			}
		}
		String[] p = maxPersonality(personality);
		return p;
	}
	
	
	
	public String[] maxPersonality(int[] personality) {
		int max1 = personality[0];
		int max2 = personality[0];
		int index1 = 0;
		int index2 = 0;
		for(int i=1; i<personality.length; i++){
			if(personality[i]>max1){
				max1 = personality[i];
				index1 = i;
			}
		}
		for(int i=1; i<personality.length; i++){
			if(i!=index1 && personality[i]>max2){
				max2 = personality[i];
				index2 = i;
			}
		}
		String[] s = new String[]{defineString(max1,index1), defineString(max2,index2)};
		
		return s;
	}

	private String defineString(int max, int index) {
		if(max>0){
			switch(index){
			case 0 : return "Openess";
			case 1 : return "Conscientiouness";
			case 2 : return "Extroversion";
			case 3 : return "Aggreableness";
			case 4 : return "Neuroticism";
			}
		}
		return null;		
	}
	
	
	
	
	
}
